#include "Common.h"
#include "DepthRendering.h"
#include "Material.h"
#include "VertexFactory.h"
#include "Render.h"
#include "RenderView.h"
#include "Renderable.h"

const ShaderType DepthOnlyVertexShader::StaticType(
	"DepthShader.hlsl", 
	"vs_3_0", 
	"VSMain", 
	ShaderType::EST_Vertex, 
	&DepthOnlyVertexShader::ShouldCache,
	&DepthOnlyVertexShader::Create,
	&DepthOnlyVertexShader::Define);

const ShaderType DepthOnlyPixelShader::StaticType(
	"DepthShader.hlsl", 
	"ps_3_0", 
	"PSMain", 
	ShaderType::EST_Pixel, 
	&DepthOnlyPixelShader::ShouldCache,
	&DepthOnlyPixelShader::Create,
	&DepthOnlyPixelShader::Define);

bool DepthOnlyVertexShader::Init()
{
	if (!Shader::Init())
		return false;

	mWorldViewProjMatrixParam.Bind(this, "WorldViewProjMatrix");
	return true;
}

void DepthOnlyVertexShader::Set(RenderView* view)
{
}

void DepthOnlyVertexShader::SetRenderable(RenderView* view, Renderable* renderable)
{
	Matrix worldMatrix(renderable->getWorldMatrix());
	Matrix worldViewProjMatrix = view->ViewProjMatrix * worldMatrix;
	mWorldViewProjMatrixParam.SetVertexShaderValue(worldViewProjMatrix);
}

DepthDrawingPolicy::DepthDrawingPolicy(const VertexFactory* vertexFactory, const Material* material)
	: MeshDrawingPolicy(vertexFactory, material)
	, mVertexShader(NULL)
	, mPixelShader(NULL)
{
	mVertexShader = material->getShader<DepthOnlyVertexShader>(vertexFactory->GetType());
	mPixelShader = material->getShader<DepthOnlyPixelShader>(vertexFactory->GetType());

	// get the pixel & vertex shader
	if (material->isMasked())
	{
	}
	else
	{
		mPixelShader = NULL;
	}
}

BoundShaderStatePtr DepthDrawingPolicy::CreateBoundShaderState()
{
	LPDIRECT3DDEVICE9 d3dDevice = Render::Instance().getDevice();
	BoundShaderState* boundShaderState = new BoundShaderState();

	boundShaderState->VertexDeclaration = mVertexFactory->getPositionDeclaration();
	boundShaderState->VertexShader = mVertexShader->getVertexShader();
	boundShaderState->PixelShader = mPixelShader ? mPixelShader->getPixelShader() : NULL;

	return BoundShaderStatePtr(boundShaderState);
}


void DepthDrawingPolicy::DrawShared(BoundShaderStatePtr& boundShaderState)
{
	boundShaderState->Set();

	mVertexFactory->Set(true);
}

void DepthDrawingPolicy::DrawRenderable(RenderView* view, Renderable* renderable)
{
	mVertexShader->Set(view);
	mVertexShader->SetRenderable(view, renderable);
	
	MeshDrawingPolicy::DrawRenderable(renderable);
	//MaterialInstance* materialInstance = renderable->getMaterial();
}